<head>
  <style> 
    body { 
      margin: 0;
      top: 0px;
      width: 100vw;
      height: 100vh;
      bottom: 0px;
      position: absolute;
      z-index: 0;
      background-image: url("./largebgg.jpg");
      background-repeat: no-repeat;
      background-size: 100% 100%;
    } 
    .header {
      position: absolute;
      top: 0;
      left: 0;
      height: 80px;
      line-height: 60px;
      width: 100%;
      background-image: url("./largetitle.png");
      background-repeat: no-repeat;
      background-size: 100%;
      text-align: center;
      color: #fff;
      font-size: 34px;
      font-weight: 600;
      z-index: 999;
    }
  </style>

  <!-- <script src="//unpkg.com/3d-force-graph"></script> -->
  <script src="./3d-force-graph.min.js"></script>
</head>

<body>
  <div class="header">关系图谱</div>
  <div id="3d-graph"></div>

  <script type="module">
    import SpriteText from "https://esm.sh/three-spritetext";
    var initData = [{
      name:'电动自行车产业',
      children:[
        {
          name:'产业链',
          children:[
            {
              name:'上游',
              children:[
                  { name:'电池' },
                  { name:'电机' },
                  { name:'控制器' },
                  { name:'配件' },
              ]
            },
            {
              name:'中游',
              children:[
                  { name:'设备' },
                  { name:'软件' },
              ]
            },
            {
              name:'下游',
              children:[
                  { name:'充电设施' },
                  { name:'回收利用' },
                  { name:'用地规划' },
              ]
            },
          ]
        },
        {
          name:'企业信息',
          children:[
            {
              name:'企业规模',
              children:[
                  { name:'生产企业12004家' },
                  { name:'销售企业22312家' },
                  { name:'专精特新企业192家' },
                  { name:'高新技术企业99家' },
              ]
            },
            {
              name:'营收',
              children:[
                  { name:'22年45亿元' },
                  { name:'23年50亿元' },
                  { name:'24年60亿元' },
              ]
            },
            {
              name:'利润',
              children:[
                  { name:'22年1000万元' },
                  { name:'23年2000万元' },
                  { name:'24年2500万元' },
              ]
            },
          ]
        },
        {
          name:'质量基础',
          children:[
            {
              name:'检验检测',
              children:[
                  { name:'检测机构23家' },
                  { name:'检测能力9231项' },
              ]
            },
            {
              name:'认证',
              children:[
                  { name:'强制性产品认证331个' },
                  { name:'出口认证49个' },
              ]
            },
            {
              name:'标准',
              children:[
                  { name:'为主起草国家标准12项' },
                  { name:'参与起草国家标准89项' },
                  { name:'为主起草行业标准113项' },
                  { name:'参与起草行业标准32项' },
              ]
            },
            {
              name:'计量',
              children:[
                  { name:'检定校准机构12家' },
                  { name:'检定校准能力149项' },
              ]
            },
          ]
        },
        {
          name:'产业创新',
          children:[
            {
              name:'知识产权',
              children:[
                  { name:'专利455413个' },
                  { name:'商标33343个' },
              ]
            },
            {
              name:'品牌认证',
              children:[
                  { name:'品字标34个' },
                  { name:'绿色认证45个' },
                  { name:'体系认证901个' },
              ]
            }
          ]
        },
      ]
    }]
    var data = {
      "nodes": [],
      "links": []
    }
    function getData(){
      data = {nodes:[],links:[]}
      deepTree(initData,'')
      console.log(data);
    }
    // 遍历格式化节点
    function deepTree(list,code,config={label:'name',children:'children',expandLevel:4}){
      list.forEach((e,i)=>{
        let codeStr = (i+1) < 10 ? code + '0'+(i+1): code + (i+1)
        let level = (code.split('').length / 2) + 1
        let show = true
        if(config.expandLevel>0){
          show = codeStr.split('').length>2*config.expandLevel?false:true
        }
        data['nodes'].push({id:codeStr,name:e[config.label],val:(6/level),group:level,show,childShow:show})
        if(codeStr.split('').length>2){
          data['links'].push({source:codeStr,target:code,show})
        }
        if(e[config.children]&&e[config.children].length){
          deepTree(e[config.children],codeStr)
        }
      })
    }
    getData()
    const Graph = new ForceGraph3D(document.getElementById('3d-graph'))
      // .jsonUrl('./miserables1.json')
      .graphData(data)
      .nodeLabel('name')
      .nodeAutoColorBy('group')
      .onNodeRightClick ( node => {
        console.log(node);
        window.open('https://cn.bing.com/search?q=' + node.name)
      })
      .onNodeClick(node => {
        let nodeLength = node.id.split('').length
        let show = node.childShow
        data['nodes'].forEach(e=>{
          if(show){
            if(e.id != node.id && e.id.substring(0,nodeLength) == node.id){
              e.show = !show
            }else if(e.id == node.id){
              e.childShow = !e.childShow
            }
          }else{
            if(e.id != node.id && e.id.substring(0,nodeLength) == node.id && e.id.split('').length-2 == nodeLength){
              e.show = !show
            }else if(e.id == node.id){
              e.childShow = !e.childShow
            }
          }
        })
        data['links'].forEach(e=>{
          if(show){
            e.source = e.source.id
            e.target = e.target.id
            if(e.target.substring(0,nodeLength) == node.id){
              e.show = !show
            }
          }else{
            e.source = e.source.id
            e.target = e.target.id
            if(e.target == node.id){
              e.show = !show
            }
          }
          
        })
        console.log(data);
        
        Graph.graphData(data);
        // const distance = 40;
        // const distRatio = 1 + distance/Math.hypot(node.x, node.y, node.z);

        // const newPos = node.x || node.y || node.z
        //   ? { x: node.x * distRatio, y: node.y * distRatio, z: node.z * distRatio }
        //   : { x: 0, y: 0, z: distance }; // special case if node is in (0,0,0)

        // Graph.cameraPosition(
        //   newPos, // new position
        //   node, // lookAt ({ x, y, z })
        //   3000  // ms transition duration
        // );
      })
      .onNodeDragEnd(node => {
        node.fx = node.x;
        node.fy = node.y;
        node.fz = node.z;
      })
      .nodeVisibility(node=>{
        return node.show
      })
      .linkVisibility(node=>{
        return node.show
      })
      .nodeThreeObject(node=>{
        const sprite = new SpriteText(node.name);
        sprite.color = '#fff';
        sprite.strokeColor = '#555'
        sprite.strokeWidth = '1'
        sprite.textHeight = 5;
        sprite.position.set(0,80/(node.group+3),0);
        return sprite;
      })
      .nodeThreeObjectExtend((node=>{
        return true
      }))
      // 设置初始化镜头视距
      Graph.cameraPosition(
        {x:0,y:0,z:500}, // new position
        3000  // ms transition duration
      );
      // 设置画布
      // const container = document.getElementById('3d-graph');
      // const canvas = container.getElementsByTagName('canvas')[0];
      // if (canvas) {
      //   // 修改 Canvas 属性
      //   // canvas.style.position = 'absolute'
      //   // canvas.style.top = '150px'
      //   // canvas.style.left = '314px'
      // } else {
      //   console.error('Canvas not found');
      // }
      
    
      // height(750).width(1200).
      Graph.backgroundColor('rgba(0, 0, 0, 0)').showNavInfo(false).nodeOpacity(1).nodeRelSize(6).nodeResolution(20).linkWidth(1).linkCurvature(0)

      // 旋转动画
      // const distance = 500;//缩放
      // let speed = 800 //转速
      // let angle = 0;
      // let timer = null
      // function autoPaly(){
      //   if(timer){
      //     clearInterval(timer)
      //     timer = null
      //   }
      //   timer = setInterval(() => {
      //     Graph.cameraPosition({
      //       x: distance * Math.sin(angle),
      //       z: distance * Math.cos(angle)
      //     });
      //     angle += Math.PI / speed;
      //   }, 10);
      // }
      // autoPaly()
      // document.getElementById('3d-graph').onmouseover = ()=>{
      //   console.log('????');
      //   if(timer){
      //     clearInterval(timer)
      //     timer = null
      //   }
      // }
      // document.getElementById('3d-graph').onmouseout = ()=>{
      //   console.log('!!!!');
      //   autoPaly()
      // }
  </script>
</body>